<?php

require_once 'EntitySerializer.php';
require_once 'RestRequest.php';

/**
 */
class RestfulServiceConsumer {

    private $lastURI = "";
    private $config = array(
        "serviceBaseURL" => "",
        "serviceClass" => "",
        "acceptType" => "application/json",
        "contentType" => "application/json",
        "method" => "post",
        "data" => "",
        "username" => null,
        "password" => null,
    );
    /**
     *
     * @var RestRequest
     */
    private $requester;

    function __construct($serviceBaseURL) {
        $this->config["serviceBaseURL"] = $serviceBaseURL;
        $this->requester = new RestRequest();
    }

    public function __call($name, $arguments) {
        $this->invokeService($name, $arguments[0]);
    }

    /**
     * <p>Calls a service method with the given parameters.
     * </p>
     *
     * <p>Note that you can do this by calling a method from this class with
     * the same name of the service name.
     * </p>
     *
     * @param string $methodName The service's method to be invoked.
     * @param array $params
     * <p>An associative array with the following form:
     * <code>
     * array(
     *  "serviceBaseURL" => "http://your.service.url?",//The service base URL. The URL given in the constructor by default.
     * "serviceClass" => "serviceClass", //An specific service, empty string by default.
     *  "acceptType" => "mime/type", //Any mime type, application/json by default.
     *  "contentType" => "mime/type",//Any mime type, application/json by default.
     *  "method" => "GET/POST", //Any HTTP method, POST by default.
     *  "data"=>mixed, //Any object you would like to send. Empty string by default.
     * )
     * </code>
     * </p>
     * <p>All these parameters are optional and have default values. Those can be set
     * or get by using the corresponding setters and getters.
     * </p>
     * 
     * @return string The response body.
     *
     * @throws  InvalidArgumentException When the HTTP method is not
     * GET, POST, PUT or DELETE.
     * @throws  RequestFailedException When request fails. This exception has the
     * response info.
     */
    public function invokeService($methodName, array $params = array()) {
        $this->requester->flush();

        $config = array_merge($this->config, $params);

        $url = $config["serviceBaseURL"];
        if (isset($config["serviceClass"])) {
            $url .= $config["serviceClass"];
        }
        $this->requester->setUrl($url . "/" . $methodName);
        $this->requester->addHeaderVariable("Accept", $config["acceptType"]);
        $this->requester->addHeaderVariable("Content-Type", $config["contentType"]);
        $this->requester->setVerb($config["method"]);
        if (strtoupper($this->requester->getVerb()) == "POST") {
            $this->requester->setRequestBody($config["data"]);
        }
        $this->requester->setUsername($config["username"]);
        $this->requester->setPassword($config["password"]);

        $this->lastURI = $this->requester->getUrl();
        $this->requester->execute();
        return $this->requester->getResponseBody();
    }

    public function getServiceBaseURL() {
        return $this->config["serviceBaseURL"];
    }

    public function setServiceBaseURL($serviceBaseURL) {
        $this->config["serviceBaseURL"] = $serviceBaseURL;
    }

    public function getAcceptType() {
        return $this->config["acceptType"];
    }

    public function setAcceptType() {
        $this->config["acceptType"] = $acceptType;
    }

    public function getContentType() {
        return $this->config["contentType"];
    }

    public function setContentType($val) {
        $this->config["contentType"] = $val;
    }

    public function getMethod() {
        return $this->config["method"];
    }

    public function setMethod($val) {
        $this->config["method"] = $val;
    }

    public function getData() {
        return $this->config["data"];
    }

    public function setData($val) {
        $this->config["data"] = $val;
    }

    public function getUriTemplate() {
        return $this->config["uriTemplate"];
    }

    public function setUriTemplate($template) {
        $this->config["uriTemplate"] = $template;
    }

    public function getResponseBody() {
        return $this->requester->getRequestBody();
    }

    public function getResponseInfo() {
        return $this->requester->getResponseInfo();
    }


    /**
     *
     * @return RestRequest
     */
    public function getRequester() {
        return $this->requester;
    }
    /**
     * Gets the last requested URI for this instance.
     * @return string the last requested URI.
     */
    public function getLastURI() {
        return $this->lastURI;
    }

}

?>
